package com.feeyo.prophet.actions.flight;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.feeyo.llm.agent.engine.*;
import com.feeyo.llm.util.JsonUtil;
import com.feeyo.prophet.exception.InterfaceQueryResult;
import com.feeyo.prophet.plugins.ConstantUtils;
import com.feeyo.prophet.pojo.action.ActionExample;
import com.feeyo.prophet.pojo.action.DateRange;
import com.feeyo.prophet.pojo.action.flight.FlightStatisticsReq;
import com.feeyo.prophet.pojo.action.flight.FlightStatisticsResp;
import com.feeyo.prophet.pojo.action.functioncall.Properties;
import com.feeyo.prophet.pojo.action.functioncall.flight.FlightStatisticsProperties;
import com.feeyo.prophet.pojo.action.functioncall.FunctionCall;
import com.feeyo.prophet.pojo.action.functioncall.ItemsBean;
import com.feeyo.prophet.pojo.action.functioncall.flight.common.BasicTypeDefaultList;
import com.feeyo.prophet.config.ParametersSingletonManager;
import com.feeyo.prophet.plugins.AnswerUtils;
import com.feeyo.prophet.plugins.DbSearchActionUtils;
import com.feeyo.prophet.plugins.FlightScheduleActionUtils;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 航班统计查询
 * @author lihu
 */
@Slf4j
public class FlightStatisticsAction implements Action {
    private final String host;
    private final Integer port;

    public FlightStatisticsAction(String host, Integer port) {
        this.host = host;
        this.port = port;
    }

    @Override
    public String human() {
        return "航班统计查询";
    }

    @Override
    public String name() {
        return "FlightStatisticsAction";
    }

    @Override
    public String eg() {
        ActionExample example = new ActionExample();
        example.setQuestion("今年1月份春秋航空公司航班量、座位数、旅客人数分别是多少？");
        example.setThought("我应该使用 FlightStatisticsAction 工具来查询特定航司（例如春秋航空公司）在特定时间范围内的航班量、座位数和旅客人数。你需要设置合适的查询参数来获得这些数据。");
        example.setAction("FlightStatisticsAction");
        Map<String, String> actionInput = new HashMap<>(){
            {
                put("fcategory", "[2]");
                put("dateRanges", "[{\"startDate\":\"2024-01-01\",\"endDate\":\"2024-01-31\"}]");
                put("airlines", "[\"9C\"]");
                put("fields", "[\"fnums\", \"fseats\", \"fpassengers\"]");
            }
        };
        example.setActionInput(actionInput);
        example.setObservation("2024年1月份春秋航空公司总计执行了13930次航班，提供了2695439个座位，运送了2107873名旅客。");
        return example.toString();
    }

    @Override
    public String description() {
        return """
                只能查询单程航班
                用于航班统计查询,给出指定多时间段,出发地到达地，航司等条件，查询航班量, 座位数, 旅客人数等
                注意支持国家-国家、国家-城市、国家-机场、城市-城市、机场-机场、城市-机场等多维度查询
                注意有些IATA城市三字码和IATA机场三字码是不同的
                """;
    }

    /**
     * 参考格式来源
     * @linlink <a href="https://learn.microsoft.com/zh-cn/azure/ai-services/openai/how-to/function-calling?tabs=non-streaming%2Cpython">...</a>
     *
     */
    @Override
    public String parameters() {
        String parameters = ParametersSingletonManager.getParameters("FlightStatisticsAction", () -> {
            FunctionCall functionCall = new FunctionCall();
            functionCall.setType("object");
            functionCall.setRequired(Lists.newArrayList("dateRanges", "fields"));
            FlightStatisticsProperties properties = new FlightStatisticsProperties();
            Properties dateProp = new Properties();
            dateProp.setStartDate(new BasicTypeDefaultList("string", "开始日期，格式: yyyy-MM-dd"));
            dateProp.setEndDate(new BasicTypeDefaultList("string", "结束日期，格式: yyyy-MM-dd"));
            properties.setDateRanges(new BasicTypeDefaultList("array", "查询日期范围数组，例如: [{'startDate':'2023-01-01', 'endDate':'2023-12-31'}]", new ItemsBean("object", null, dateProp, Lists.newArrayList("startDate", "endDate")), new ArrayList<>()));
            properties.setFcategory(new BasicTypeDefaultList("array", "航段类型数组 以下枚举值均表示双向航班：'0:国内-国内(有时直接简述为国内),1:国内-地区(有时直接简述为地区),2:国内-国际(有时直接简述为国际),3:地区-地区,4:地区-国际,5:国际-国际'", new ItemsBean("number", Lists.newArrayList(0, 1, 2, 3, 4, 5), null, null), new ArrayList<>()));
            properties.setAirlines(new BasicTypeDefaultList("array", "航司IATA二字码 例如:[\"9C\"]", new ItemsBean("string", null, null, null), new ArrayList<>()));
            properties.setFservice(new BasicTypeDefaultList("string", "服务类型 枚举值:'F:货运;J:客运'", Lists.newArrayList("F", "J")));
            properties.setDeptAirportCode(new BasicTypeDefaultList("string", "（出发地机场/出港机场/机场）IATA三字码"));
            properties.setArrAirportCode(new BasicTypeDefaultList("string", "（到达地机场/进港机场）IATA三字码"));
            properties.setDeptCityCode(new BasicTypeDefaultList("string", "出发地城市IATA三字码"));
            properties.setArrCityCode(new BasicTypeDefaultList("string", "到达地城市IATA三字码"));
            properties.setDeptProvinceName(new BasicTypeDefaultList("string", "出发地省名称, 例如: 安徽"));
            properties.setArrProvinceName(new BasicTypeDefaultList("string", "到达地省名称, 例如: 四川"));
            properties.setDeptCountryCode(new BasicTypeDefaultList("string", "出发地国家IATA二字码)"));
            properties.setArrCountryCode(new BasicTypeDefaultList("string", "到达地国家IATA二字码"));
            properties.setDeptContinentCode(new BasicTypeDefaultList("string", "出发地洲英文名称", Lists.newArrayList("Africa", "Asia", "Europe", "North America", "South America", "Oceania")));
            properties.setArrContinentCode(new BasicTypeDefaultList("string", "到达地洲英文名称", Lists.newArrayList("Africa", "Asia", "Europe", "North America", "South America", "Oceania")));
            properties.setSingleType(new BasicTypeDefaultList("string", "非必须字段。出港或者进港，出港为0，进港为1", Lists.newArrayList("0", "1")));
            ResultScheme result = result();
            List<ResultScheme.ResultAttach> resultAttachList = result.getResultAttachList();
            List<String> fieldsList = resultAttachList.stream().map(ResultScheme.ResultAttach::getName).toList();
            properties.setFields(new BasicTypeDefaultList("array", "返回结果字段集合(根据需要多选), 各个字段含义解释如下: " + JsonUtil.marshalToString(resultAttachList)
                    + "。可选填字段如下: " + String.join(", ", fieldsList) + ",你需要尽量全面的选出适用字段。可以选多，不要选少。", new ItemsBean("string"), 1));
            functionCall.setProperties(properties);
            return functionCall.toString();
        });
        return parameters;
    }

    private void dataConsistencyCheck(FlightStatisticsReq input) {
        String singleType = input.getSingleType();
        List<String> deptAirportCode = input.getDeptAirportCode();
        List<String> arrAirportCode = input.getArrAirportCode();
        if (StringUtils.isNotEmpty(singleType)) {
            if (!ConstantUtils.COMMON_STRING_ZERO.equals(singleType) && !ConstantUtils.COMMON_STRING_ONE.equals(singleType)) {
                throw new RuntimeException("类型错误");
            }
            // 出港
            if(ConstantUtils.COMMON_STRING_ZERO.equals(singleType)){
                if(CollectionUtils.isNotEmpty(arrAirportCode) && CollectionUtils.isEmpty(deptAirportCode)){
                    input.setDeptAirportCode(input.getArrAirportCode());
                    input.setArrAirportCode(null);
                }
                if(CollectionUtils.isNotEmpty(input.getArrCityCode()) && CollectionUtils.isEmpty(input.getDeptCityCode())){
                    input.setDeptCityCode(input.getArrCityCode());
                    input.setArrCityCode(null);
                }
            }
            // 进港
            if(ConstantUtils.COMMON_STRING_ONE.equals(singleType)){
                if(CollectionUtils.isNotEmpty(deptAirportCode) && CollectionUtils.isEmpty(arrAirportCode)){
                    input.setArrAirportCode(input.getDeptAirportCode());
                    input.setDeptAirportCode(null);
                }
                if(CollectionUtils.isNotEmpty(input.getDeptCityCode()) && CollectionUtils.isEmpty(input.getArrCityCode()) ){
                    input.setArrCityCode(input.getDeptCityCode());
                    input.setDeptCityCode(null);
                }
            }
        }
    }

    @Override
    public ParameterScheme defaultParameters() {
        Map<String, ParameterScheme.Property> properties = new HashMap<>();
        ParameterScheme.Property dateRangesProperty = new ParameterScheme.Property();
        dateRangesProperty.setType("array");
        dateRangesProperty.setDescription("查询日期范围数组，例如: [{'startDate':'2023-01-01', 'endDate':'2023-12-31'}]");
        ParameterScheme.Property.Items dateRangesItems = new ParameterScheme.Property.Items();
        dateRangesItems.setType("object");
        Map<String, ParameterScheme.Property> dateRangesItemsProperties = new HashMap<>();
        dateRangesItemsProperties.put("startDate", new ParameterScheme.Property("string", "开始日期，格式: yyyy-MM-dd"));
        dateRangesItemsProperties.put("endDate", new ParameterScheme.Property("string", "结束日期，格式: yyyy-MM-dd"));
        dateRangesItems.setProperties(dateRangesItemsProperties);
        dateRangesItems.setRequired(List.of("startDate", "endDate"));
        dateRangesProperty.setItems(dateRangesItems);
        properties.put("dateRanges", dateRangesProperty);
        properties.put("fcategory", new ParameterScheme.Property("array", "航段类型数组 枚举值:'0:国内飞国内(有时直接简述为国内),1:国内飞地区(有时直接简述为地区),2:国内飞国际(有时直接简述为国际),3:地区飞地区,4:地区飞国际,5:国际飞国际'", new ParameterScheme.Property.Items("number", List.of(0, 1, 2, 3, 4, 5), null, null), null, null, null, null));
        properties.put("airlines", new ParameterScheme.Property("array", "航司IATA二字码 例如:[\"9C\"]", new ParameterScheme.Property.Items("string", null, null, null), null, null, null, null));
        properties.put("airports", new ParameterScheme.Property("array", "机场IATA三字码数组 例如:[\"PVG\"]", new ParameterScheme.Property.Items("string", null, null, null), null, null, null, null));
        properties.put("fservice", new ParameterScheme.Property("string", "服务类型 枚举值:'F:货运;J:客运'", null, null, List.of("F", "J"), null, null));
        properties.put("deptAirportCode", new ParameterScheme.Property("string", "出发地机场(IATA机场三字码)"));
        properties.put("arrAirportCode", new ParameterScheme.Property("string", "到达地机场(IATA机场三字码)"));
        properties.put("deptCityCode", new ParameterScheme.Property("string", "出发地城市(IATA城市三字码)"));
        properties.put("arrCityCode", new ParameterScheme.Property("string", "到达地城市(IATA城市三字码)"));
        properties.put("deptProvinceName", new ParameterScheme.Property("string", "出发地省名称, 例如: 安徽"));
        properties.put("arrProvinceName", new ParameterScheme.Property("string", "到达地省名称, 例如: 四川"));
        properties.put("deptCountryCode", new ParameterScheme.Property("string", "出发地国家(IATA国家二字码)"));
        properties.put("arrCountryCode", new ParameterScheme.Property("string", "到达地国家(IATA国家二字码)"));
        properties.put("deptContinentCode", new ParameterScheme.Property("string", "出发地洲英文名称", null, null, List.of("Africa", "Asia", "Europe", "North America", "South America", "Oceania"), null, null));
        properties.put("arrContinentCode", new ParameterScheme.Property("string", "到达地洲英文名称", null, null, List.of("Africa", "Asia", "Europe", "North America", "South America", "Oceania"), null, null));
        List<ResultScheme.ResultAttach> resultAttachList = result().getResultAttachList();
        List<String> fieldsList = resultAttachList.stream().map(ResultScheme.ResultAttach::getName).toList();
        properties.put("fields", new ParameterScheme.Property("array", "返回结果字段集合(根据需要多选), 字段含义: " + JsonUtil.marshalToString(resultAttachList)
                + "，可选字段: " + String.join(", ", fieldsList), new ParameterScheme.Property.Items("string", null, null, null), null, null, 1, null));
        ParameterScheme parameterScheme = new ParameterScheme("object", List.of("dateRanges", "fields"), properties);
        return parameterScheme;
    }

    @Override
    public ResultScheme result() {
        ResultScheme resultScheme = new ResultScheme();
        List<ResultScheme.ResultAttach> resultAttachList = Lists.newArrayList();
        resultAttachList.add(new ResultScheme.ResultAttach("actSum", "integer", "实际执行量, 航班量"));
        resultAttachList.add(new ResultScheme.ResultAttach("planSum", "integer", "计划执行量"));
        resultAttachList.add(new ResultScheme.ResultAttach("canlSum", "integer", "取消执行量"));
        resultAttachList.add(new ResultScheme.ResultAttach("delaySum", "integer", "延误执行量"));
        resultAttachList.add(new ResultScheme.ResultAttach("totalSeatSum", "integer", "座位数"));
        resultAttachList.add(new ResultScheme.ResultAttach("soldSeatSum", "integer", "旅客人数"));
        resultAttachList.add(new ResultScheme.ResultAttach("startDate", "string", "开始时间, 格式:yyyy-MM-dd eg:'2023-01-01'"));
        resultAttachList.add(new ResultScheme.ResultAttach("endDate", "string", "截止时间, 格式:yyyy-MM-dd eg:'2023-01-31'"));
        resultAttachList.add(new ResultScheme.ResultAttach("fcategory", "string", "航班种类名称 eg:0 enum:'0:国内-国内,1:国内-地区,2:国内-国际,3:地区-地区,4:地区-国际,5:国际-国际'"));
        resultAttachList.add(new ResultScheme.ResultAttach("fservice", "string", "航班服务类型名称 eg:'F' enum:'F:货运,J:客运'"));
        resultAttachList.add(new ResultScheme.ResultAttach("airport", "string", "机场IATA三字码"));
        resultAttachList.add(new ResultScheme.ResultAttach("inAirport", "integer", "进港量"));
        resultAttachList.add(new ResultScheme.ResultAttach("outAirport", "integer", "出港量"));
        resultAttachList.add(new ResultScheme.ResultAttach("singleType", "string", "出发或者到达"));
        resultScheme.setResultAttachList(resultAttachList);
        return resultScheme;
    }

    /**
     * @param question
     * @param input
     * @return
     */
    @Override
    public ActionResult run(String question, String input, ExecuteOptions options) {
        try {
            FlightStatisticsReq req = JSON.parseObject(input, FlightStatisticsReq.class);
            dataConsistencyCheck(req);
            log.info("FlightStatisticsAction run input:{}", JsonUtil.marshalToString(req));
            List<DateRange> dateRanges = req.getDateRanges();
            if (CollectionUtils.isEmpty(dateRanges)) {
                return new ActionResult(HttpStatus.BAD_REQUEST.value(), "查询日期必须存在,请使用 conversation action 让用户补充这些参数");
            }
            String fservice = req.getFservice();
            // 获取各个维度的条件
            List<Integer> fcategory = req.getFcategory();
            String fcategoryCollect = null;
            if (null != fcategory) {
                fcategoryCollect = fcategory.stream()
                        .map(String::valueOf)
                        .collect(Collectors.joining(","));
            }
            List<String> airlines = req.getAirlines();
            List<String> fields = req.getFields();
            // 提取出发参数
            String depType = "0";
            List<String> depCodes = Lists.newArrayList();
            if(CollectionUtils.isNotEmpty(req.getDeptAirportCode())){
                depType = "1";
                depCodes = req.getDeptAirportCode();
            }
            if(CollectionUtils.isNotEmpty(req.getDeptCityCode())){
                depType = "2";
                depCodes = req.getDeptCityCode();
            }
            if(CollectionUtils.isNotEmpty(req.getDeptProvinceName())){
                depType = "3";
                depCodes = req.getDeptProvinceName();
            }
            if(CollectionUtils.isNotEmpty(req.getDeptCountryCode())){
                depType = "4";
                depCodes = req.getDeptCountryCode();
            }
            if(CollectionUtils.isNotEmpty(req.getDeptContinentCode())){
                depType = "5";
                depCodes = req.getDeptContinentCode();
            }
            // 提取到达参数
            String arrType = "0";
            List<String> arrCodes = Lists.newArrayList();
            if(CollectionUtils.isNotEmpty(req.getArrAirportCode())){
                arrType = "1";
                arrCodes = req.getArrAirportCode();
            }
            if(CollectionUtils.isNotEmpty(req.getArrCityCode())){
                arrType = "2";
                arrCodes = req.getArrCityCode();
            }
            if(CollectionUtils.isNotEmpty(req.getArrProvinceName())){
                arrType = "3";
                arrCodes = req.getArrProvinceName();
            }
            if(CollectionUtils.isNotEmpty(req.getArrCountryCode())){
                arrType = "4";
                arrCodes = req.getArrCountryCode();
            }
            if(CollectionUtils.isNotEmpty(req.getArrContinentCode())){
                arrType = "5";
                arrCodes = req.getArrContinentCode();
            }
            // 按照 航线类型(fcategory), 航司(airlines), 出发地到达地(depCodes, arrCodes) 四种维度条件排列组合调用接口.
            // 00. 000
            if (CollectionUtils.isEmpty(fcategory) && CollectionUtils.isEmpty(airlines) && (CollectionUtils.isEmpty(depCodes) && CollectionUtils.isEmpty(arrCodes))) {
                String allRouteType = "1,2,3,4,5";
                String allType = "1";
                List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(allRouteType, allType, depCodes, allType, arrCodes, dateRanges, fservice, airlines);
                return getFlightStatisticsResp(fields, flightStatisticsResp, input);
            }
            // 01. 001
            if (CollectionUtils.isEmpty(fcategory) && CollectionUtils.isEmpty(airlines)) {
                // 1. 出发地不为空，到达地为空
                if (CollectionUtils.isNotEmpty(depCodes) && CollectionUtils.isEmpty(arrCodes)) {
                    arrType = depType;
                    if(depType.compareTo(ConstantUtils.COMMON_STRING_TWO)>0){
                        return new ActionResult( HttpStatus.BAD_REQUEST.value(), "单项查询仅支持机场，城市维度");
                    }
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, null);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
                // 2. 出发地为空，到达地不为空
                if (CollectionUtils.isEmpty(depCodes) && CollectionUtils.isNotEmpty(arrCodes)) {
                    depType = arrType;
                    if(arrType.compareTo(ConstantUtils.COMMON_STRING_TWO)>0){
                        return new ActionResult(HttpStatus.BAD_REQUEST.value(), "单项查询仅支持机场，城市维度");
                    }
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, null);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
                // 3.出发地到达地都不为空
                if (CollectionUtils.isNotEmpty(depCodes) && CollectionUtils.isNotEmpty(arrCodes)) {
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, null);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
            }
            // 02. 010
            if (CollectionUtils.isEmpty(fcategory) && CollectionUtils.isNotEmpty(airlines)) {
                //进出港为空
                if (CollectionUtils.isEmpty(depCodes) && CollectionUtils.isEmpty(arrCodes)) {
                    List<FlightStatisticsResp> flightStatisticsResp = searchByAirlines(fcategoryCollect, airlines, dateRanges, fservice);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
            }
            // 03. 011
            if (CollectionUtils.isEmpty(fcategory) && CollectionUtils.isNotEmpty(airlines)) {
                // 1. 出发
                if (CollectionUtils.isNotEmpty(depCodes) && CollectionUtils.isEmpty(arrCodes)) {
                    arrType = depType;
                    if(depType.compareTo(ConstantUtils.COMMON_STRING_TWO)>0){
                        return new ActionResult(HttpStatus.BAD_REQUEST.value(), "单项查询仅支持机场，城市维度");
                    }
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, airlines);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
                // 2. 到达
                if (CollectionUtils.isEmpty(depCodes) && CollectionUtils.isNotEmpty(arrCodes)) {
                    depType = arrType;
                    if(arrType.compareTo(ConstantUtils.COMMON_STRING_TWO)>0){
                        return new ActionResult(HttpStatus.BAD_REQUEST.value(), "单项查询仅支持机场，城市维度");
                    }
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, airlines);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
                // 3. 都不为空
                if(CollectionUtils.isNotEmpty(depCodes) && CollectionUtils.isNotEmpty(arrCodes)){
                    // 航司 + 出发地,到达地
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, airlines);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
            }
            // 04. 100 都是空
            if (CollectionUtils.isNotEmpty(fcategory) && CollectionUtils.isEmpty(airlines)) {
                // 都是空
                if (CollectionUtils.isEmpty(depCodes) && CollectionUtils.isEmpty(arrCodes)) {
                    List<FlightStatisticsResp> flightStatisticsResp = searchByFcategory(fcategoryCollect, dateRanges, fservice);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
            }
            // 05. 101
            if (CollectionUtils.isNotEmpty(fcategory) && CollectionUtils.isEmpty(airlines)) {
                // 1. 出发
                if (CollectionUtils.isNotEmpty(depCodes) && CollectionUtils.isEmpty(arrCodes)) {
                    arrType = depType;
                    if(depType.compareTo(ConstantUtils.COMMON_STRING_TWO)>0){
                        return new ActionResult( HttpStatus.BAD_REQUEST.value(), "单项查询仅支持机场，城市维度");
                    }
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, null);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
                // 2. 到达
                if (CollectionUtils.isEmpty(depCodes) && CollectionUtils.isNotEmpty(arrCodes)) {
                    depType = arrType;
                    if(arrType.compareTo(ConstantUtils.COMMON_STRING_TWO)>0){
                        return new ActionResult(HttpStatus.BAD_REQUEST.value(), "单项查询仅支持机场，城市维度");
                    }
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, null);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
                // 3. 进出港
                if(CollectionUtils.isNotEmpty(depCodes) && CollectionUtils.isNotEmpty(arrCodes)){
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, null);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
            }
            // 06. 110 -> 今年1月份春秋航司发出的国内航班量是多少
            if (CollectionUtils.isNotEmpty(fcategory) && CollectionUtils.isNotEmpty(airlines)) {
                // 都是空
                if (CollectionUtils.isEmpty(depCodes) && CollectionUtils.isEmpty(arrCodes)) {
                    List<FlightStatisticsResp> flightStatisticsResp = searchByAirlines(fcategoryCollect, airlines, dateRanges, fservice);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
            }
            // 07. 111
            if (CollectionUtils.isNotEmpty(fcategory) && CollectionUtils.isNotEmpty(airlines)) {
                // 1. 出港
                if (CollectionUtils.isNotEmpty(depCodes) && CollectionUtils.isEmpty(arrCodes)) {
                    arrType = depType;
                    if(depType.compareTo(ConstantUtils.COMMON_STRING_TWO)>0){
                        return new ActionResult( HttpStatus.BAD_REQUEST.value(), "单项查询仅支持机场，城市维度");
                    }
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, airlines);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
                // 2. 进港
                if (CollectionUtils.isEmpty(depCodes) && CollectionUtils.isNotEmpty(arrCodes)) {
                    depType = arrType;
                    if(arrType.compareTo(ConstantUtils.COMMON_STRING_TWO)>0){
                        return new ActionResult( HttpStatus.BAD_REQUEST.value(), "单项查询仅支持机场，城市维度");
                    }
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, airlines);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
                // 3. 进出港
                if(CollectionUtils.isNotEmpty(depCodes) && CollectionUtils.isNotEmpty(arrCodes)){
                    List<FlightStatisticsResp> flightStatisticsResp = searchByDepArr(fcategoryCollect, depType, depCodes, arrType, arrCodes, dateRanges, fservice, airlines);
                    return getFlightStatisticsResp(fields, flightStatisticsResp, input);
                }
            }
            return new ActionResult( HttpStatus.BAD_REQUEST.value(), "不支持这种条件查询");
        } catch (Throwable e) {
            log.error("error", e);
            return new ActionResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), "解析发生错误，请思考后再调用？");
        }
    }

    /**
     * 对象转化输出
     */
    private ActionResult getFlightStatisticsResp(List<String> fields, List<FlightStatisticsResp> flightStatisticsRespList, String input) {
        List<JSONObject> listNeed = FlightScheduleActionUtils.getNeedDataList(fields, flightStatisticsRespList);
        ResultScheme resultScheme = FlightScheduleActionUtils.resultScheme(fields, result());
        return AnswerUtils.answer(name(), input, listNeed, resultScheme);
    }

    public List<FlightStatisticsResp> searchByFcategory(String routeType, List<DateRange> dateRanges, String fservice) throws Exception {
        List<FlightStatisticsResp> result = Lists.newArrayList();
        for (DateRange dateRange : dateRanges) {
            InterfaceQueryResult resp = DbSearchActionUtils.queryFcategory(host, port, dateRange.getStartDate(), dateRange.getEndDate(), routeType, fservice);
            if(resp.getStatusCode() != HttpStatus.OK.value()){
                continue;
            }
            JSONObject json = JSONObject.parseObject(resp.getResponseText());
            if (null == json) {
                continue;
            }
            JSONObject data = json.getJSONObject("data");
            if (null == data) {
                continue;
            }
            JSONArray row = data.getJSONArray("rows");
            if (null == row) {
                continue;
            }
            if (!row.isEmpty()) {
                List<FlightStatisticsResp> statisticsRespList = Lists.newArrayList();
                for (int i = 0; i < row.size(); i++) {
                    JSONObject jsonObject = JSON.parseObject(row.getString(i));
                    FlightStatisticsResp flightStatisticsResp = JSON.parseObject(row.getString(i), FlightStatisticsResp.class);
                    flightStatisticsResp.setTotalSeatSum(Long.valueOf(jsonObject.getOrDefault("seatNum", "0").toString()));
                    flightStatisticsResp.setSoldSeatSum(Long.valueOf(jsonObject.getOrDefault("passengerNum", "0").toString()));
                    statisticsRespList.add(flightStatisticsResp);
                }
                result.addAll(statisticsRespList);
            }
        }
        return result;
    }

    public List<FlightStatisticsResp> searchByAirlines(String routeType, List<String> airlines, List<DateRange> dateRanges, String fservice) throws Exception {
        List<FlightStatisticsResp> result = Lists.newArrayList();
        for (String airline : airlines) {
            for (DateRange dateRange : dateRanges) {
                String resp = DbSearchActionUtils.queryAirline(host, port, dateRange.getStartDate(), dateRange.getEndDate(), airline, routeType, fservice);
                JSONObject json = JSONObject.parseObject(resp);
                if (null == json) {
                    continue;
                }
                JSONObject data = json.getJSONObject("data");
                if (null == data) {
                    continue;
                }
                JSONArray row = data.getJSONArray("rows");
                if (null == row) {
                    continue;
                }
                if (!row.isEmpty()) {
                    List<FlightStatisticsResp> statisticsRespList = Lists.newArrayList();
                    for (int i = 0; i < row.size(); i++) {
                        JSONObject jsonObject = JSON.parseObject(row.getString(i));
                        FlightStatisticsResp flightStatisticsResp = JSON.parseObject(row.getString(i), FlightStatisticsResp.class);
                        flightStatisticsResp.setTotalSeatSum(Long.valueOf(jsonObject.getOrDefault("seatNum", "0").toString()));
                        flightStatisticsResp.setSoldSeatSum(Long.valueOf(jsonObject.getOrDefault("passengerNum", "0").toString()));
                        flightStatisticsResp.setInAirport(Long.valueOf(jsonObject.getOrDefault("inAirport", "0").toString()));
                        flightStatisticsResp.setOutAirport(Long.valueOf(jsonObject.getOrDefault("outAirport", "0").toString()));
                        statisticsRespList.add(flightStatisticsResp);
                    }
                    result.addAll(statisticsRespList);
                }
            }
        }
        return result;

    }

    public List<FlightStatisticsResp> searchByDepArr(String routeType,
                                                     String forgType, List<String> depCodes,
                                                     String fdstType, List<String> arrCodes,
                                                     List<DateRange> dateRanges,
                                                     String fservice, List<String> airlines) throws Exception {
        List<FlightStatisticsResp> result = Lists.newArrayList();
        for (DateRange dateRange : dateRanges) {
            String resp = DbSearchActionUtils.queryDepArr(host, port,
                    dateRange.getStartDate(), dateRange.getEndDate(),
                    depCodes, arrCodes,
                    forgType, fdstType, routeType, "0", fservice, airlines);
            JSONObject json = JSONObject.parseObject(resp);
            if (null == json) {
                continue;
            }
            JSONObject data = json.getJSONObject("data");
            if (null == data) {
                continue;
            }
            result.add(JSON.parseObject(String.valueOf(data), FlightStatisticsResp.class));
        }
        return result;
    }
}